import time
from wave import open as _openwav
from ossaudiodev import open as _opendsp
from os import sep as _OS_SEP


VERSION = 2.0

w = 'w'  # Width
l = 'l'  # Length
a = 'a'  # Individual area
A = 'A'  # Total area (sum(a[0], a[1]...a[n]))
jwla = 'wla'  # "Joint 'w', 'l', 'a'"
af = 'area_factor'
wla = (w, l, a)
wlaA = (w, l, a, A)
leaf_n = 'leaf_n'  # Leaf number index

sleep = time.sleep
timestamp = time.time

_beep_normal = _openwav('click.wav', 'rb')
_beep_warn = _openwav('poomp.wav', 'rb')
_format = 16
_channels = 2
_framerate = 22050


def path_and_base(file_obj, what=None):
    """Takes a file object and returns its path and file base name.

    Without the argument 'what' (what to return) it defaults to the
    full path plus the file name without its extension (base name).
    This is useful when working with different file types with the same
    base name such as a log file and a main data file (for example
    20090317.dat and 20090317.log).  Opening only one file the basename
    can be extracted and used to automatically open the other.

    The option 'one_dir_up' is intended as a display string for a GUI
    application instead of showing the full path which may be too long
    to be practical.

    A word of caution: the doctest below works only on *nix where the
    path separator is '/'.  I could not figure out how to make 'if'
    statements work properly to make it cross-platform ;-)

    >>> class ObjectWithNameAttr: pass
    >>> objwithnameattr = ObjectWithNameAttr()
    >>> objwithnameattr.name = '/somepath/somedirectory/importantfile.ext'
    >>>
    >>> path_and_base(objwithnameattr)
    '/somepath/somedirectory/importantfile'
    >>> path_and_base(objwithnameattr, 'full_path')
    '/somepath/somedirectory'
    >>> path_and_base(objwithnameattr, 'file_name')
    'importantfile.ext'
    >>> path_and_base(objwithnameattr, 'one_dir_up')
    '.../somedirectory/importantfile.ext'
    """
    chopped_path = file_obj.name.split(_OS_SEP)
    chopped_file_name = chopped_path.pop().split('.')
    file_ext = chopped_file_name.pop()
    path = _OS_SEP.join(chopped_path)
    file_basename = ''.join(chopped_file_name)
    file_name = '.'.join((file_basename, file_ext))
    if not what and path:
        name = _OS_SEP.join((path, file_basename))
    elif what in ('path', 'path_name', 'full_path'):
        name = path
    elif what in ('file_name',):
        name = file_name
    elif what in ('one_dir_up',):
        if path:
            name = _OS_SEP.join(('...', chopped_path[-1], file_name))
        else:
            name = _OS_SEP.join(('.', file_name))
    else:
        name = file_basename
    return name


class FakeDSP:
    def write(self, x):
        pass

    def close(self):
        pass


def _dsp_wrapper():
    try:
        dsp = _opendsp('/dev/dsp','w')
        dsp.setparameters(_format, _channels, _framerate)
    except IOError:
        dsp = FakeDSP()
    return dsp


def notify(n=1, kind='normal'):
    if kind == 'normal':
        for i in range(n):
            dsp = _dsp_wrapper()
            _beep_normal.rewind()
            dsp.write(_beep_normal.readframes(_beep_normal._nframes))
            dsp.close()
            if n > 1:
                sleep(0.125)
    else:
        dsp = _dsp_wrapper()
        _beep_warn.rewind()
        dsp.write(_beep_warn.readframes(_beep_warn._nframes))
        dsp.close()


class LeafArea:
    def __init__(self, data):
        self.data = data
        self.data_names = ('timestamp', 'leaf_n', 'a', 'l', 'w')

    def retrieve(self, r=0):
        run = r or len(self.data)
        prev_s = run - 1
        current_run_copy = {}
        for dn in self.data_names:
            current_run_copy[dn] = self.data[run][dn][:]
        while current_run_copy['leaf_n'][0] > 1:
            earliest_leaf = current_run_copy['leaf_n'][0]
            slice_ = self.data[prev_s]['leaf_n'].index(earliest_leaf - 1) + 1
            for dn in self.data_names:
                current_run_copy[dn] = self.data[prev_s][dn][0:slice_] + \
                                       current_run_copy[dn]
            prev_s -= 1
        return current_run_copy

